﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using PessModel;
using System.Net.Http;
using System.Collections.Specialized;
using System.Threading.Tasks;
using System.Web.Security;
using System.Web.Profile;
using PessMvc.Models;
using PessMvc.Helpers;
using System.Text;
using Newtonsoft.Json;
using System.IO;

namespace PessMvc.Controllers
{

    public class RegistrationsController : Controller
    {
        private PESSEntities db = new PESSEntities();

        // GET: Registrations
        
        [Authorize]
        public ActionResult Index()
        {
            if (User.IsInRole("Admin"))
            {
                return View(db.Registrations.OrderByDescending(r=>r.Status).OrderBy(r=>r.OverTime).ToList());
            }
            else
                return RedirectToAction("Register");
        }

        // GET: Registrations/Details/5
        [Authorize(Roles = "Admin")]
        public ActionResult Details(Guid? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Registration registration = db.Registrations.Find(id);
            if (registration == null)
            {
                return HttpNotFound();
            }
            return View(registration);
        }

        // GET: Registrations/Create
        //public ActionResult Create()
        //{
        //    return View();
        //}

        // POST: Registrations/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        //[HttpPost]
        //[ValidateAntiForgeryToken]
        //public ActionResult Create([Bind(Include = "UserId,ProfessionalTitle,Preference,PayId,Status,PayerName,Amount,Paid,Refund,OverTime,PayType,PayPassword")] Registration registration)
        //{
        //    if (ModelState.IsValid)
        //    {
        //        registration.UserId = Guid.NewGuid();
        //        db.Registrations.Add(registration);
        //        db.SaveChanges();
        //        return RedirectToAction("Index");
        //    }

        //    return View(registration);
        //}

        // GET: Registrations/Edit/5
        [Authorize(Roles = "Admin")]
        public ActionResult Edit(Guid? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Registration registration = db.Registrations.Find(id);
            if (registration == null)
            {
                return HttpNotFound();
            }
            return View(registration);
        }

        // POST: Registrations/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        [Authorize(Roles = "Admin")]
        public ActionResult Edit([Bind(Include = "UserId,ProfessionalTitle,Preference,PayId,Status,PayerName,Amount,Paid,Refund,OverTime,PayType,PayPassword")] Registration registration)
        {
            if (ModelState.IsValid)
            {
                db.Entry(registration).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(registration);
        }

        // GET: Registrations/Delete/5
        [Authorize(Roles = "Admin")]
        public ActionResult Delete(Guid? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Registration registration = db.Registrations.Find(id);
            if (registration == null)
            {
                return HttpNotFound();
            }
            return View(registration);
        }

        // POST: Registrations/Delete/5
        [Authorize(Roles = "Admin")]
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(Guid id)
        {
            Registration registration = db.Registrations.Find(id);
            db.Registrations.Remove(registration);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        
        public ActionResult Register()
        {
            if (User.Identity.IsAuthenticated)
            {
                //get basic items for radio buttons
                var basicitems = db.RegistrationOptions.Where(ro => ro.Type == 0);
                //get addon items for check boxes
                var addonitems = db.RegistrationOptions.Where(ro => ro.Type == 1);
                ViewBag.BasicItems = basicitems;
                ViewBag.AddonItems = addonitems;

                MembershipUser user = Membership.GetUser();
                string userid = user.ProviderUserKey.ToString();

                Registration reg = db.Registrations.Find(Guid.Parse(userid));
                return View(reg);
            }
            else
            {
                
                return RedirectToAction("RegLogOn", "Account");
            }
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        [Authorize]
        public ActionResult Register(RegistrationViewModel model)
        {
            if (ModelState.IsValid)
            {
                MembershipUser user = Membership.GetUser();
                string userid=user.ProviderUserKey.ToString();
                //check if registration exists
                Registration reg = db.Registrations.Find(Guid.Parse(userid));
                if(reg==null)
                {
                    reg = new Registration();
                    reg.UserId = Guid.Parse(userid);
                    reg.Preference = model.Preference;
                    RegistrationOption ro = db.RegistrationOptions.Find(model.BasicItemId);
                    if(ro!=null)
                        reg.RegistrationOptions.Add(ro);
                    RegistrationOption ro_addon = db.RegistrationOptions.Find(model.AddonItemId);
                    if (ro_addon != null)
                        reg.RegistrationOptions.Add(ro_addon);
                    db.Registrations.Add(reg);
                }
                else
                {
                    reg.Preference = model.Preference;
                    reg.RegistrationOptions.Clear();
                    RegistrationOption ro = db.RegistrationOptions.Find(model.BasicItemId);
                    if (ro != null)
                        reg.RegistrationOptions.Add(ro);
                    RegistrationOption ro_addon = db.RegistrationOptions.Find(model.AddonItemId);
                    if (ro_addon != null)
                        reg.RegistrationOptions.Add(ro_addon);
                }
                db.SaveChanges();
                return RedirectToAction("ConfirmPersonalInformation");
            }
            
            //get basic items for radio buttons
            var basicitems = db.RegistrationOptions.Where(ro => ro.Type == 0);
            //get addon items for check boxes
            var addonitems = db.RegistrationOptions.Where(ro => ro.Type == 1);
            ViewBag.BasicItems = basicitems;
            ViewBag.AddonItems = addonitems;
            return View();
        }

        [Authorize]
        public ActionResult ConfirmPersonalInformation()
        {
            UserModel model = new UserModel() { UserName = Membership.GetUser().UserName };
            ProfileBase profile = ProfileBase.Create(model.UserName);
            model.FirstName = profile["FirstName"] == null ? "" : profile["FirstName"].ToString();
            model.LastName = profile["LastName"] == null ? "" : profile["LastName"].ToString();
            model.PhoneNumber = profile["PhoneNumber"] == null ? "" : profile["PhoneNumber"].ToString();
            model.SchoolName = profile["Organization"] == null ? "" : profile["Organization"].ToString();
            model.ZipCode = profile["ZipCode"] == null ? "" : profile["ZipCode"].ToString();
            model.StateProvince = profile["StateProvince"] == null ? "" : profile["StateProvince"].ToString();
            model.Country = profile["Country"] == null ? "" : profile["Country"].ToString();
            model.City = profile["City"] == null ? "" : profile["City"].ToString();
            model.Address1 = profile["Address1"] == null ? "" : profile["Address1"].ToString();
            model.Address2 = profile["Address2"] == null ? "" : profile["Address2"].ToString();
            model.ProfessionalTitle = profile["ProfessionalTitle"] == null ? "" : profile["ProfessionalTitle"].ToString();
            model.Email = Membership.GetUser().Email;
            model.Fax = profile["Fax"] == null ? "" : profile["Fax"].ToString();
            return View(model);
        }

        [HttpPost]
        [Authorize]
        public ActionResult ConfirmPersonalInformation(UserModel model)
        {
            if (ModelState.IsValid)
            {
                MembershipUser user = Membership.GetUser(model.UserName);
                ProfileBase profile = ProfileBase.Create(model.UserName);
                profile["FirstName"] = model.FirstName;
                profile["LastName"] = model.LastName;
                profile["PhoneNumber"] = model.PhoneNumber;
                profile["Organization"] = model.SchoolName;
                profile["ZipCode"] = model.ZipCode;
                profile["StateProvince"] = model.StateProvince;
                profile["Country"] = model.Country;
                profile["City"] = model.City;
                profile["Address1"] = model.Address1;
                profile["Address2"] = model.Address2;
                profile["ProfessionalTitle"] = model.ProfessionalTitle;
                profile["Fax"] = model.Fax;
                profile.Save();
                return RedirectToAction("ConfirmRegistration");
            }
            return View(model);
        }

        [Authorize]
        public ActionResult ConfirmRegistration()
        {
            MembershipUser user = Membership.GetUser();
            string userid = user.ProviderUserKey.ToString();
            //check if registration exists
            Registration model = db.Registrations.Find(Guid.Parse(userid));
            UserModel usermodel = new UserModel() { UserName = user.UserName };
            ProfileBase profile = ProfileBase.Create(usermodel.UserName);
            usermodel.FirstName = profile["FirstName"] == null ? "" : profile["FirstName"].ToString();
            usermodel.LastName = profile["LastName"] == null ? "" : profile["LastName"].ToString();
            usermodel.PhoneNumber = profile["PhoneNumber"] == null ? "" : profile["PhoneNumber"].ToString();
            usermodel.SchoolName = profile["Organization"] == null ? "" : profile["Organization"].ToString();
            usermodel.ZipCode = profile["ZipCode"] == null ? "" : profile["ZipCode"].ToString();
            usermodel.StateProvince = profile["StateProvince"] == null ? "" : profile["StateProvince"].ToString();
            usermodel.Country = profile["Country"] == null ? "" : profile["Country"].ToString();
            usermodel.City = profile["City"] == null ? "" : profile["City"].ToString();
            usermodel.Address1 = profile["Address1"] == null ? "" : profile["Address1"].ToString();
            usermodel.Address2 = profile["Address2"] == null ? "" : profile["Address2"].ToString();
            usermodel.ProfessionalTitle = profile["ProfessionalTitle"] == null ? "" : profile["ProfessionalTitle"].ToString();
            usermodel.Email = user.Email;
            usermodel.Fax = profile["Fax"] == null ? "" : profile["Fax"].ToString();
            ViewBag.UserInfo = usermodel;
            return View(model);
        }

        [HttpPost]
        [Authorize]
        public async Task<ActionResult> ConfirmRegistration(PaymentViewModel model)
        {
            string passcode = "";
            MembershipUser user = Membership.GetUser();
            Guid? UserID = new Guid(user.ProviderUserKey.ToString());
            ProfileBase profile = ProfileBase.Create(user.UserName);

            using(var client =new HttpClient())
            {
                string cert = "mWWx1fBGqEqU8JS5FNJQPAjdE7aPmmtXl3gA9YVqlj8thGU2cd6W9o0fZLhbKIalo6pNvBCN9KAwc1nrHmMIGE8ujlXItZOJ1WrF03Gz94ElxAXbjI41LknuGl9av6Xm";
                string sysId = "031";
                string itemId = "031-01";
                string projectid = "12581";
                string objId = UserID.ToString().Substring(0, 30);
                string otherid = "";
                string objName = profile["FirstName"].ToString()+ " " +profile["LastName"].ToString();
                string amount = model.Amount.ToString("0.00");
                string remove = "";
                string returnType = "data";
                string specialValue = "";
                UrlHelper u = new UrlHelper(this.ControllerContext.RequestContext);
                string returnURL = Request.Url.Scheme+"://"+Request.Url.Host+":"+Request.Url.Port+u.Action("PayResult","Registrations");
                string firstCert = cert.Substring(0, 1);
                string source = firstCert + sysId
                    + firstCert + itemId
                    + firstCert + objId
                    + firstCert + otherid
                    + firstCert + objName
                    + firstCert + amount
                    + firstCert + remove
                    + firstCert + returnType
                    + firstCert + specialValue
                    + firstCert + returnURL
                    + cert;
                string sign = Utility.GetMd5Hash(source);
                Encoding UTF8 = Encoding.UTF8;
                //var values = new NameValueCollection
                //{
                //    {"sign",sign},
                //    {"sysId",sysId},
                //    {"itemId",itemId},
                //    {"projectid",projectid},
                //    {"objId",HttpUtility.UrlEncode(objId, UTF8)},
                //    {"otherid",HttpUtility.UrlEncode(otherid, UTF8)},
                //    {"objName",HttpUtility.UrlEncode(objName, UTF8)},
                //    {"specialValue",HttpUtility.UrlEncode(specialValue, UTF8)},
                //    {"returnURL",HttpUtility.UrlEncode(returnURL, UTF8)},
                //    {"amount",amount},
                //     {"returnType",returnType},
                //};
                string urlparams = 
                    "?sign="+sign
                    +"&sysId="+sysId
                    +"&itemId="+itemId
                    +"&projectid="+projectid
                    +"&objId="+HttpUtility.UrlEncode(objId, UTF8)
                    +"&otherid="+HttpUtility.UrlEncode(otherid, UTF8)
                    +"&objName="+HttpUtility.UrlEncode(objName, UTF8)
                    +"&specialValue="+HttpUtility.UrlEncode(specialValue, UTF8)
                    +"&returnURL="+HttpUtility.UrlEncode(returnURL, UTF8)
                    + "&amount=" + HttpUtility.UrlEncode(amount, UTF8)
                    +"&returnType="+returnType;

                var result = await client.GetStringAsync("http://pay.ecnu.edu.cn/pay/itemDeal3.html" + urlparams);
                dynamic response = JsonConvert.DeserializeObject(result);
                if (response.returnCode=="00")
                {
                    passcode = response.payPassword;
                    return Redirect("http://pay.ecnu.edu.cn/pay_en/dealPay.html?pwd=" + passcode);
                }
                else
                {
                    ViewBag.Msg = "Error Code: "+response.returnCode;
                }
            }

            Registration reg = db.Registrations.Find(UserID);
            UserModel usermodel = new UserModel() { UserName = user.UserName };
            usermodel.FirstName = profile["FirstName"] == null ? "" : profile["FirstName"].ToString();
            usermodel.LastName = profile["LastName"] == null ? "" : profile["LastName"].ToString();
            usermodel.PhoneNumber = profile["PhoneNumber"] == null ? "" : profile["PhoneNumber"].ToString();
            usermodel.SchoolName = profile["Organization"] == null ? "" : profile["Organization"].ToString();
            usermodel.ZipCode = profile["ZipCode"] == null ? "" : profile["ZipCode"].ToString();
            usermodel.StateProvince = profile["StateProvince"] == null ? "" : profile["StateProvince"].ToString();
            usermodel.Country = profile["Country"] == null ? "" : profile["Country"].ToString();
            usermodel.City = profile["City"] == null ? "" : profile["City"].ToString();
            usermodel.Address1 = profile["Address1"] == null ? "" : profile["Address1"].ToString();
            usermodel.Address2 = profile["Address2"] == null ? "" : profile["Address2"].ToString();
            usermodel.ProfessionalTitle = profile["ProfessionalTitle"] == null ? "" : profile["ProfessionalTitle"].ToString();
            usermodel.Email = user.Email;
            usermodel.Fax = profile["Fax"] == null ? "" : profile["Fax"].ToString();
            ViewBag.UserInfo = usermodel;
            return View(reg);
        }

        [Authorize]
        public ActionResult PayResultTest()
        {
            return View();
        }

        [HttpPost]
        [Authorize]
        public ActionResult PayResult()
        {
            string sign = Request["sign"];
            string version = Request["version"];
            string sysId = Request["sysId"];
            string itemId = Request["itemId"];
            string objId = Request["objId"];
            string otherId = Request["otherId"];
            string objName = Request["objName"];
            string amount = Request["amount"];
            string paid = Request["paid"];
            string refund = Request["refund"];
            string overTime = Request["overTime"];
            string status = Request["status"];
            string projectId = Request["projectId"];
            string payId = Request["payId"];
            string payPassword = Request["payPassword"];
            string specialValue = Request["specialValue"];
            string payType = Request["payType"];
            string sysCert = "mWWx1fBGqEqU8JS5FNJQPAjdE7aPmmtXl3gA9YVqlj8thGU2cd6W9o0fZLhbKIalo6pNvBCN9KAwc1nrHmMIGE8ujlXItZOJ1WrF03Gz94ElxAXbjI41LknuGl9av6Xm";
            string firstSC = sysCert.Substring(0, 1);
            ViewBag.Error = "";

            string[] result = new string[]{
                 firstSC, version, firstSC, sysId, firstSC, itemId, firstSC, objId, firstSC, otherId,
                 firstSC, objName, firstSC, amount, firstSC, paid, firstSC, refund, firstSC, overTime,
                 firstSC, status, firstSC, projectId, firstSC, payId, firstSC, payPassword,
                 firstSC, specialValue, firstSC, payType, sysCert
            };

            Registration reg = null;

            if(Utility.VerifyMd5Hash(string.Join("", result), sign))
            {
                MembershipUser user = Membership.GetUser();
                Guid? UserID = new Guid(user.ProviderUserKey.ToString());
                reg = db.Registrations.Find(UserID);
                if (reg.TotalAmountRMB == decimal.Parse(paid))
                {
                    reg.PayId = payId;
                    reg.Status = int.Parse(status);
                    reg.PayerName = objName;
                    reg.Amount = decimal.Parse(amount);
                    reg.Paid = decimal.Parse(paid);
                    reg.Refund = decimal.Parse(refund);
                    reg.OverTime = overTime;
                    reg.PayType = payType;
                    reg.PayPassword = payPassword;
                    PessModel.RegistrationOption BasicItem = null;
                    PessModel.RegistrationOption AddonItem = null;
                    //prepare email information
                    if (reg.RegistrationOptions.Count > 0)
                    {
                        BasicItem = reg.RegistrationOptions.FirstOrDefault();
                        AddonItem = reg.RegistrationOptions.Where(ro => ro.Type == 1).FirstOrDefault(); //1 is for optional items
                    }
                    ProfileBase profile = ProfileBase.Create(user.UserName);
                    UserModel usermodel = new UserModel() { UserName = user.UserName };
                    usermodel.FirstName = profile["FirstName"] == null ? "" : profile["FirstName"].ToString();
                    usermodel.LastName = profile["LastName"] == null ? "" : profile["LastName"].ToString();
                    usermodel.PhoneNumber = profile["PhoneNumber"] == null ? "" : profile["PhoneNumber"].ToString();
                    usermodel.SchoolName = profile["Organization"] == null ? "" : profile["Organization"].ToString();
                    usermodel.ZipCode = profile["ZipCode"] == null ? "" : profile["ZipCode"].ToString();
                    usermodel.StateProvince = profile["StateProvince"] == null ? "" : profile["StateProvince"].ToString();
                    usermodel.Country = profile["Country"] == null ? "" : profile["Country"].ToString();
                    usermodel.City = profile["City"] == null ? "" : profile["City"].ToString();
                    usermodel.Address1 = profile["Address1"] == null ? "" : profile["Address1"].ToString();
                    usermodel.Address2 = profile["Address2"] == null ? "" : profile["Address2"].ToString();
                    usermodel.ProfessionalTitle = profile["ProfessionalTitle"] == null ? "" : profile["ProfessionalTitle"].ToString();
                    usermodel.Email = user.Email;
                    usermodel.Fax = profile["Fax"] == null ? "" : profile["Fax"].ToString();
                     //send email
                    using (StreamReader reader = new StreamReader(Server.MapPath("~/App_Data/templates/registrationconfirm.txt")))
                    {
                        //string shortdescription = archive.SchoolComment.Replace("&lt;", "<").Replace("&gt;", ">").Replace("<br/>", "\n");
                        //string text_abstract= archive.CountyEBComment.Replace("&lt;", "<").Replace("&gt;", ">").Replace("<br/>", "\n"); 
                        string text = reader.ReadToEnd();
                        text = text.Replace("[Name]", usermodel.FirstName+" "+usermodel.LastName);
                        text = text.Replace("[confirmationnumber]", reg.PayId);
                        text = text.Replace("[ProfessionalTitle]", usermodel.ProfessionalTitle);
                        text = text.Replace("[Affiliation]", usermodel.SchoolName);
                        text = text.Replace("[Address]", usermodel.Address1+(usermodel.Address2==""?"":" , "+usermodel.Address2)+(usermodel.City == "" ? "" : ", " + usermodel.City)+(usermodel.StateProvince == "" ? "" : ", " + usermodel.StateProvince)+(usermodel.ZipCode == "" ? "" : ", " + usermodel.ZipCode));
                        text = text.Replace("[Email]", usermodel.Email);
                        text = text.Replace("[PhoneNumber]", usermodel.PhoneNumber);
                        text = text.Replace("[FaxNumber]", usermodel.Fax);
                        text = text.Replace("[Preference]", reg.Preference==0?"Non-vegetarian":"Vegetarian");
                        text = text.Replace("[HuangPuRiver]", AddonItem != null ? (DateTime.Now.Date <= AddonItem.EarlyDate ? " ¥" + AddonItem.EarlyFeeRMB.ToString("N") + " (Early bird)" : " ¥" + AddonItem.RegularFeeRMB.ToString("N")) : "");
                        text = text.Replace("[Registration]", BasicItem!=null?(DateTime.Now.Date<=BasicItem.EarlyDate?" ¥" + BasicItem.EarlyFeeRMB.ToString("N")+" (Early bird)" :" ¥" + BasicItem.RegularFeeRMB.ToString("N")):"");
                        text = text.Replace("[Total]", reg.Paid.Value.ToString("N"));
                        text = text.Replace("[PayType]", reg.PayType);
                        text = text.Replace("[PayDate]", reg.OverTime);
                        Utility.SendMail("Registration Confirmation for " + usermodel.FirstName+" "+usermodel.LastName, text, usermodel.Email);
                    }
                }
                else
                {
                    reg.Status = 0;
                    ViewBag.Error = "The amount is wrong.";
                }
                db.SaveChanges();
            }
            else
            {
                ViewBag.Error = "The payment signatures does not match.";
            }

            return View(reg);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }

    }
}
